package com.starry.module.member.config;

import com.starry.core.security.config.SecurityProperties;
import com.starry.core.security.utils.SecurityErrorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;

import java.util.Arrays;

/**
 * OAuth2 资源服务端配置
 *
 * @Author xiaoke
 */
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(jsr250Enabled = true, securedEnabled = true)
public class ResourceServerConfig {
    private final JwtAuthenticationConverter jwtAuthenticationConverter;
    private final SecurityProperties securityProperties;

    public ResourceServerConfig(JwtAuthenticationConverter jwtAuthenticationConverter, SecurityProperties securityProperties) {
        this.jwtAuthenticationConverter = jwtAuthenticationConverter;
        this.securityProperties = securityProperties;
    }

    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorize -> authorize
                        //放行接口的配置，被放行的接口上不能有权限注解，e.g. @PreAuthorize，否则无效
                        .requestMatchers(securityProperties.getIgnoreAuth()).permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        // 自定义解析设置
                        .jwt(jwt -> jwt
                                .jwtAuthenticationConverter(jwtAuthenticationConverter)
                        )
                        // 添加未携带token和权限不足异常处理
                        .accessDeniedHandler(SecurityErrorUtil::exceptionHandler)
                        .authenticationEntryPoint(SecurityErrorUtil::exceptionHandler)
                );
        return http.build();
    }

    /**
     * 密码加密
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
